package com.cropdoctor.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cropdoctor.common.CustomException;
import com.cropdoctor.common.Result;
import com.cropdoctor.mapper.HistoryImgDisMapper;
import com.cropdoctor.mapper.ImgIdfDisMapper;
import com.cropdoctor.model.constants.FruitAndVegetableClassification;
import com.cropdoctor.model.dto.HistoryImgDisDto;
import com.cropdoctor.model.dto.ImgDisDto;
import com.cropdoctor.model.dto.jsonToObj;
import com.cropdoctor.model.po.HistoryImgDisPo;
import com.cropdoctor.service.ImgIdfDisService;
import com.cropdoctor.util.AliOssUtil;
import com.cropdoctor.util.ContextGet;
import com.cropdoctor.util.HttpUtils;
import com.cropdoctor.util.Img2Base64;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ImgIdfDisServiceImpl implements ImgIdfDisService {
    @Autowired
    ImgIdfDisMapper imgIdfDisMapper;

    @Autowired
    HistoryImgDisMapper historyImgDisMapper;

    @Value("${aliyuncommon.method}")
    String method;
    @Value("${aliyuncommon.appcode}")
    String appcode;

    @Autowired
    FruitAndVegetableClassification classification;

    @Autowired
    AliOssUtil ossUtil;

    public Result<List<HistoryImgDisDto>> getHistoryByData(Long userId,String name,LocalDateTime dateTime,Long id){
        LambdaQueryWrapper<HistoryImgDisPo> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(userId != 0,HistoryImgDisPo::getIdUser,userId)
                .eq(name!= null && !name.isEmpty(),HistoryImgDisPo::getName,name)
                .eq(id != 0,HistoryImgDisPo::getIdH,id)
                .le(dateTime != null,HistoryImgDisPo::getCreateDateTime,dateTime)
                .orderByDesc(dateTime != null,HistoryImgDisPo::getCreateDateTime);

        List<HistoryImgDisPo> historyImgDisPos = historyImgDisMapper.selectList(queryWrapper);
        List<HistoryImgDisDto> historyImgDisDtos = new ArrayList<>();

        if(historyImgDisPos.size() != 0){
            historyImgDisPos.forEach(item->{
                HistoryImgDisDto historyImgDisDto = new HistoryImgDisDto();
                List<String> confidences = JSON.parseArray(item.getConfidences(), String.class);
                List<String> classifications = JSON.parseArray(item.getClassifications(), String.class);

                historyImgDisDto.setConfidences(confidences);
                historyImgDisDto.setClassifications(classifications);
                historyImgDisDto.setCreateDateTime(item.getCreateDateTime());
                historyImgDisDto.setUrl(item.getUrl());
                historyImgDisDto.setIdH(item.getIdH());

                historyImgDisDtos.add(historyImgDisDto);
            });
        }else{
            throw new CustomException("该用户的历史数据为空!");
        }
        return Result.success(historyImgDisDtos);
    }

    @Override
    public Result<List<HistoryImgDisDto>> getHistory(Long userId, String name, LocalDateTime dateTime,Long id) {
        return getHistoryByData(userId,name,dateTime,id);
    }



    public List<ImgDisDto> json2ImgDisDto(String json,String name){
        Map jsonMap = JSON.parseObject(json, Map.class);
        JSONArray jsonArray = (JSONArray)jsonMap.get("图像分类实体信息");

        String status = jsonMap.get("图像分类状态").toString(); //返回数据状态

        List<jsonToObj> jsonToObjs = jsonArray.toJavaList(jsonToObj.class);

        List<ImgDisDto> imgDisDtos = jsonToObjs.stream().map(item -> {
            ImgDisDto imgDisDto = new ImgDisDto();
            imgDisDto.setCategory(item.分类名称);
            imgDisDto.setConfidence(item.分类置信度);
            imgDisDto.setName(name);

            return imgDisDto;
        }).collect(Collectors.toList());

        return imgDisDtos;
    }

    public Result<List<ImgDisDto>> doPost(String path, MultipartFile img,String name,String host) {
        Map<String, String> headers = new HashMap<String, String>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appcode);
        //根据API的要求，定义相对应的Content-Type
        headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        Map<String, String> querys = new HashMap<String, String>();
        Map<String, String> bodys = new HashMap<String, String>();

        String filename = img.getOriginalFilename();
        File tempFile = null;
        byte[] bytes = null;
        String absolutePath = "";
        try {
            tempFile = File.createTempFile("oss", "temp");
            absolutePath = tempFile.getAbsolutePath();//临时文件路径
            bytes = img.getBytes();
            img.transferTo(tempFile);
        } catch (IOException e) {
            e.printStackTrace();
            throw new CustomException("创建临时文件失败!");
        }
        try {
            bodys.put("IMAGE",Img2Base64.jpgToBase(absolutePath));
        } catch (IOException e) {
            e.printStackTrace();
            throw new CustomException("图片转base64失败!");
        }finally {
            if(tempFile != null) tempFile.delete();//程序退出时删除临时文件
        }
        HttpResponse response = null;
        try {
            log.info("开始查询..");
            response = HttpUtils.doPost(host, path , method, headers, querys, bodys);
            log.info("获得查询结果..");
        } catch (Exception e) {
            e.printStackTrace();
            log.info("查询失败!");
            throw new CustomException("处理图片失败!");
        }
        List<ImgDisDto> imgDisDtos = null;
        String url = null;
        try {
            imgDisDtos = json2ImgDisDto(EntityUtils.toString(response.getEntity()), name);
        } catch (IOException e) {
            e.printStackTrace();
            throw new CustomException("结果集解析失败!");
        }


        //获取原始的文件名
        String originalFilename = img.getOriginalFilename();
        //在oss中存储名字就是UUID + 文件的后缀名
        String objectName = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));
        url = ossUtil.upload(bytes, "history/"+"dis/"+objectName);

        ArrayList<String> classifications = new ArrayList<>();
        ArrayList<String> confidences = new ArrayList<>();

        imgDisDtos.forEach(item->{
            classifications.add(item.getCategory());
            confidences.add(item.getConfidence());

        });

        String clsJson = JSON.toJSONString(classifications);
        String confidencesJson = JSON.toJSONString(confidences);
        HistoryImgDisPo historyImgDisPo = new HistoryImgDisPo();
        historyImgDisPo.setConfidences(confidencesJson);
        historyImgDisPo.setClassifications(clsJson);
        historyImgDisPo.setIdUser(ContextGet.getUserId());
        historyImgDisPo.setName(name);
        historyImgDisPo.setUrl(url);

        int result = historyImgDisMapper.insert(historyImgDisPo);//插入数据库

        if(result <= 0){
            throw new CustomException("添加历史记录失败!");
        }

        return Result.success(imgDisDtos);
    }

    @Override
    public Result<List<ImgDisDto>> imgIdf(MultipartFile img, String path) throws IOException {
        return doPost(classification.getPathByKey(path),img,path, classification.getHostByKey(path));
    }

}
